home *** CD-ROM | disk | FTP | other *** search
/ Stone Design / Stone Design.iso / Stone_Friends / Wave / WavesWorld / Source / IBPalettes / WW3DKit / RIBRotate.m < prev    next >
Encoding:
Text File  |  1995-03-22  |  8.1 KB  |  314 lines

  1. // copyright 1993 Michael B. Johnson; some portions copyright 1994, MIT
  2. // see COPYRIGHT for reuse legalities
  3. //
  4.  
  5. #import "RIBRotate.h"
  6.  
  7. @implementation RIBRotate
  8.  
  9. + initialize { return [RIBRotate setVersion:1], self; }
  10.  
  11. - updateMatrix
  12. {
  13.   double  theta;
  14.   double   alphaHat, versineOfAlphaHat;
  15.   RtPoint  aHat;
  16.   RtFloat  divisor;
  17.  
  18.  
  19.   N3D_CopyMatrix(N3DIdentityMatrix, myMatrix);
  20.   theta = toRadians(angle);
  21.   alphaHat = theta;
  22.  
  23.   // three simple cases are rotation about x, y, or z
  24.   if ((dx == 1.0) && (dy == 0.0) && (dz == 0.0))  // X
  25.   {  myMatrix[1][1] = (RtFloat)cos(theta); 
  26.      myMatrix[1][2] = (RtFloat)sin(theta); 
  27.      myMatrix[2][1] = -1. * (RtFloat)sin(theta); 
  28.      myMatrix[2][2] = (RtFloat)cos(theta); 
  29.      return self;
  30.   }
  31.   if ((dx == 0.0) && (dy == 1.0) && (dz == 0.0))  // Y
  32.   {  myMatrix[0][0] = (RtFloat)cos(theta); 
  33.      myMatrix[0][2] = -1. * (RtFloat)sin(theta); 
  34.      myMatrix[2][0] = (RtFloat)sin(theta); 
  35.      myMatrix[2][2] = (RtFloat)cos(theta); 
  36.      return self;
  37.   }
  38.   if ((dx == 0.0) && (dy == 0.0) && (dz == 1.0))  // Z
  39.   {  myMatrix[0][0] = (RtFloat)cos(theta); 
  40.      myMatrix[0][1] = (RtFloat)sin(theta); 
  41.      myMatrix[1][0] = -1. * (RtFloat)sin(theta); 
  42.      myMatrix[1][1] = (RtFloat)cos(theta); 
  43.      return self;
  44.   }
  45.  
  46.   // yuck.  we now have to do rotation about an arbitrary axis.  oh joy.
  47.  
  48.   divisor = (RtFloat)(sqrt((dx * dx) + (dy * dy) + (dz * dz)));
  49.   aHat[0] = dx/divisor;
  50.   aHat[1] = dy/divisor;
  51.   aHat[2] = dz/divisor;
  52.   versineOfAlphaHat = 1 - cos(alphaHat);
  53.  
  54.   myMatrix[0][0] = 1 + (((aHat[0] * aHat[0]) - 1) * versineOfAlphaHat);
  55.   myMatrix[0][1] = (aHat[2] * sin(alphaHat)) + (aHat[0] * aHat[1] * versineOfAlphaHat);
  56.   myMatrix[0][2] = (-1 * aHat[1] * sin(alphaHat)) + (aHat[2] * aHat[0] * versineOfAlphaHat);
  57.   myMatrix[1][0] = (-1 * aHat[2] * sin(alphaHat)) + (aHat[0] * aHat[1] * versineOfAlphaHat);
  58.   myMatrix[1][1] = 1 + (((aHat[1] * aHat[1]) - 1) * versineOfAlphaHat);
  59.   myMatrix[1][2] = (aHat[0] * sin(alphaHat)) + (aHat[1] * aHat[0] * versineOfAlphaHat);
  60.   myMatrix[2][0] = (aHat[1] * sin(alphaHat)) + (aHat[2] * aHat[0] * versineOfAlphaHat);
  61.   myMatrix[2][1] = (-1 * aHat[0] * sin(alphaHat)) + (aHat[1] * aHat[0] * versineOfAlphaHat);
  62.   myMatrix[2][2] = 1 + (((aHat[2] * aHat[2]) - 1) * versineOfAlphaHat);
  63.  
  64.   //NXLogError("RIBRotate (-updateMatrix):\n");
  65.   //NXLogError("\t%f %f %f %f\n",  myMatrix[0][0], myMatrix[0][1], myMatrix[0][2], myMatrix[0][3]);
  66.   //NXLogError("\t%f %f %f %f\n",  myMatrix[1][0], myMatrix[1][1], myMatrix[1][2], myMatrix[1][3]);
  67.   //NXLogError("\t%f %f %f %f\n",  myMatrix[2][0], myMatrix[2][1], myMatrix[2][2], myMatrix[2][3]);
  68.   //NXLogError("\t%f %f %f %f\n", myMatrix[3][0], myMatrix[3][1], myMatrix[3][2], myMatrix[3][3]);
  69.  
  70.   return self;
  71. }
  72.  
  73. - init
  74. {
  75.   [super init];
  76.   angle = 90.0;
  77.   dx = 1.0;
  78.   dy = 0.0;
  79.   dz = 0.0;
  80.  
  81.   [self updateMatrix];
  82.  
  83.   return self;
  84. }
  85.  
  86. - awake
  87. {
  88.   [super awake];
  89.   [self updateMatrix];
  90.  
  91.   return self;
  92. }
  93.  
  94. - setAngle:(RtFloat)newAngle dx:(RtFloat)newDX dy:(RtFloat)newDY dz:(RtFloat)newDZ
  95. {
  96.   angle = newAngle;
  97.   dx = newDX;
  98.   dy = newDY;
  99.   dz = newDZ;
  100.   [self updateMatrix];
  101.  
  102.   return self;
  103. }
  104.  
  105. - (BOOL)isLerpable { return YES; }
  106.  
  107. // note: because we've made the WWSampleList "safe" for having
  108. // multiple samples with the same data, it's perfectly valid to return
  109. // yourself or b
  110. - lerpWith:b by:(float)uValue
  111. {
  112.    id      newMe = nil;
  113.    RtFloat  angleA, dxA, dyA, dzA;
  114.    RtFloat  angleB, dxB, dyB, dzB;
  115.  
  116.     if (([self class] != [b class]) || (uValue <= 0.0))
  117.     {  return self;
  118.     }
  119.  
  120.     if (uValue >= 1.0)
  121.     {  return b;
  122.     }
  123.  
  124.     newMe = [super lerpWith:b by:uValue]; // this makes a copy for us
  125.  
  126.     // okay, now do the specific stuff for this class
  127.     [self getAngle:&angleA dx:&dxA dy:&dyA dz:&dzA];
  128.     [b getAngle:&angleB dx:&dxB dy:&dyB dz:&dzB];
  129.     [newMe setAngle:(angleA + ((angleB - angleA) * uValue))
  130.               dx:(dxA + ((dxB - dxA) * uValue))
  131.               dy:(dyA + ((dyB - dyA) * uValue))
  132.               dz:(dzA + ((dzB - dzA) * uValue))];
  133.  
  134.     return newMe;
  135. }
  136.  
  137.  
  138. - lerpSelfWith:b by:(float)uValue
  139. {
  140.   RtFloat  angleA, dxA, dyA, dzA;
  141.   RtFloat  angleB, dxB, dyB, dzB;
  142.  
  143.    if (([self class] != [b class]) || (uValue <= 0.0))
  144.    {  return self;
  145.    }
  146.  
  147.    if (uValue >= 1.0)
  148.    {  return b;
  149.    }
  150.  
  151.    [super lerpSelfWith:b by:uValue]; // this makes a copy for us
  152.  
  153.    // okay, now do the specific stuff for this class
  154.    [self getAngle:&angleA dx:&dxA dy:&dyA dz:&dzA];
  155.    [b getAngle:&angleB dx:&dxB dy:&dyB dz:&dzB];
  156.    [self setAngle:(angleA + ((angleB - angleA) * uValue))
  157.              dx:(dxA + ((dxB - dxA) * uValue))
  158.              dy:(dyA + ((dyB - dyA) * uValue))
  159.              dz:(dzA + ((dzB - dzA) * uValue))];
  160.  
  161.    return self;
  162. }
  163.  
  164.  
  165. - (BOOL)isMoot
  166. {
  167.   if (!angle)  {  return YES; }
  168.   return NO;
  169. }
  170.  
  171. - (BOOL)theSameAs:otherRIBCommand
  172. {
  173.   RtFloat  theAngle, theDX, theDY, theDZ;
  174.  
  175.  
  176.   [otherRIBCommand getAngle:&theAngle dx:&theDX dy:&theDY dz:&theDZ];
  177.   if (angle != theAngle)
  178.   {  return NO;
  179.   }
  180.   if (dx != theDX)
  181.   {  return NO;
  182.   }
  183.   if (dy != theDY)
  184.   {  return NO;
  185.   }
  186.   if (dz != theDZ)
  187.   {  return NO;
  188.   }
  189.  
  190.   return [super theSameAs:otherRIBCommand];
  191. }
  192.  
  193. - setDX:(RtFloat)newDX dy:(RtFloat)newDY dz:(RtFloat)newDZ
  194. {
  195.   dx = newDX;
  196.   dy = newDY;
  197.   dz = newDZ;
  198.  
  199.   N3D_CopyMatrix(N3DIdentityMatrix, myMatrix);
  200.   myMatrix[3][0] = dx;
  201.   myMatrix[3][1] = dy;
  202.   myMatrix[3][2] = dz;
  203.  
  204.   return self;
  205. }
  206.  
  207. - getAngle:(RtFloat *)anglePtr dx:(RtFloat *)dxPtr dy:(RtFloat *)dyPtr dz:(RtFloat *)dzPtr
  208. {
  209.   *anglePtr = angle;
  210.   *dxPtr = dx;
  211.   *dyPtr = dy;
  212.   *dzPtr = dz;
  213.  
  214.   return self;
  215. }
  216.  
  217. - renderSelf:(WW3DCamera *)camera startingAt:(RtFloat)shutterOpenTime endingAt:(RtFloat)shutterCloseTime 
  218. {
  219.   RiRotate(angle, dx, dy, dz);
  220.  
  221.   return self;
  222. }
  223.  
  224. - transformCTM:(WW3DAttributeState *)attributeState startingAt:(RtFloat)shutterOpenTime endingAt:(RtFloat)shutterCloseTime
  225.   RtMatrix  aMatrix, tmpMatrix;
  226.  
  227.  
  228.   [attributeState getTransformMatrix:aMatrix];
  229.   N3DMultiplyMatrix(myMatrix, aMatrix, tmpMatrix);
  230.   [attributeState setTransformMatrix:tmpMatrix];
  231.  
  232.   //NXLogError("RIBRotate myMatrix (-transformCTM:startingAt:endingAt):\n");
  233.   //NXLogError("\t%f %f %f %f\n",  myMatrix[0][0], myMatrix[0][1], myMatrix[0][2], myMatrix[0][3]);
  234.   //NXLogError("\t%f %f %f %f\n",  myMatrix[1][0], myMatrix[1][1], myMatrix[1][2], myMatrix[1][3]);
  235.   //NXLogError("\t%f %f %f %f\n",  myMatrix[2][0], myMatrix[2][1], myMatrix[2][2], myMatrix[2][3]);
  236.   //NXLogError("\t%f %f %f %f\n", myMatrix[3][0], myMatrix[3][1], myMatrix[3][2], myMatrix[3][3]);
  237.   //NXLogError("RIBRotate aMatrix (-transformCTM:startingAt:endingAt):\n");
  238.   //NXLogError("\t%f %f %f %f\n",  aMatrix[0][0], aMatrix[0][1], aMatrix[0][2], aMatrix[0][3]);
  239.   //NXLogError("\t%f %f %f %f\n",  aMatrix[1][0], aMatrix[1][1], aMatrix[1][2], aMatrix[1][3]);
  240.   //NXLogError("\t%f %f %f %f\n",  aMatrix[2][0], aMatrix[2][1], aMatrix[2][2], aMatrix[2][3]);
  241.   //NXLogError("\t%f %f %f %f\n", aMatrix[3][0], aMatrix[3][1], aMatrix[3][2], aMatrix[3][3]);
  242.  
  243.   return self; 
  244. }
  245.  
  246. - (BOOL)isMotionBlurrable { return YES; }
  247.  
  248. - writeEve:(NXStream *)stream atTabLevel:(int)tab
  249. {
  250.    int  i;
  251.  
  252.  
  253.    for (i = 0; i < tab; i++)
  254.    {  NXPrintf(stream, "\t");
  255.    }
  256.    NXPrintf(stream, "Rotate %f %f %f %f;", angle, dx, dy, dz); 
  257.    return self;
  258. }
  259.  
  260. - writeInventorAtTime:(float)currentTime to:(NXStream *)stream atTabLevel:(int)tab
  261. {
  262.    int  i;
  263.  
  264.  
  265.    for (i = 0; i < tab; i++)
  266.    {  NXPrintf(stream, "\t");
  267.    }
  268.    NXPrintf(stream, "Rotation {\n");
  269.    for (i = 0; i < (tab+1); i++)
  270.    {  NXPrintf(stream, "\t");
  271.    }
  272.    NXPrintf(stream, "rotation %f %f %f   %f\n", dx, dy, dz, angle);
  273.    for (i = 0; i < tab; i++)
  274.    {  NXPrintf(stream, "\t");
  275.    }
  276.    NXPrintf(stream, "}");
  277.  
  278.    return self;
  279.  
  280. }
  281. #define typeVector "ffff"
  282. #define typeValues &angle, &dx, &dy, &dz
  283.  
  284. - read:(NXTypedStream*)stream 
  285. {
  286.     int version;
  287.     [super read:stream];
  288.  
  289. NX_DURING
  290.     version = NXTypedStreamClassVersion(stream,"RIBRotate");
  291.     if (version == 0) NXReadTypes(stream,"i",&version), version=1;
  292.     if (version == 1)
  293.     {  NXReadTypes(stream,typeVector,typeValues);
  294.     } 
  295. NX_HANDLER
  296.    NXLogError("in read: %s, exception [%d] raised.\n", 
  297.                  [[self class] name], NXLocalHandler.code);
  298.    return nil;
  299. NX_ENDHANDLER
  300.     return self;
  301. }
  302.  
  303. - write:(NXTypedStream*)stream 
  304. {
  305.     [super write:stream];
  306.  
  307.     NXWriteTypes(stream,typeVector, typeValues);
  308.  
  309.     return self;
  310. }
  311.  
  312. @end
  313.